#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#include <wiringPi.h>

typedef unsigned char uint8;
typedef unsigned int  uint16;
typedef unsigned long uint32;

uint32 databuf;
/*
//初始化引脚
//上电1s内不操作，维持电平稳定
*/
void GPIO_init(int gpio_pin)
{
	pinMode(gpio_pin, OUTPUT); // set mode to output
	digitalWrite(gpio_pin, 1); // output a high level
	
    sleep(1);
	
	return;
}

/*
//起始信号
	1.主机初状态是高电平，要超过1s稳定电平
	2.主机再拉低延时18ms-30ms
	3.主机末状态是高电平，等待
*/
void DHT11_start(int gpio_pin)
{	
	pinMode(gpio_pin, OUTPUT);
	digitalWrite(gpio_pin, 0);
	
	delay(25);
	
	digitalWrite(gpio_pin, 1);
	pinMode(gpio_pin, INPUT);
	pullUpDnControl(gpio_pin, PUD_UP);	//当引脚被配置为输入(INPUT)模式，使用函数pullUpDnControl来激活其内部的上拉电阻或下拉电阻
	
	delayMicroseconds(27);
	
	return;
}

/*
//主机接受数据
	1.主机接受到从机回复的响应信号
	2.格式0——54us的低电平+23到27us的高电平
	  格式1——54us的低电平+68到74us的高电平
	3.思路：从识别到低电平开始，然后去除掉掉前面54秒的低电平还有
*/
uint8 DHT11_read(int gpio_pin)
{
	uint8 crc, i;
	
	if (0 == digitalRead(gpio_pin))			//主机接收到从机发送的响应信号（低电平）
	{
		while(!digitalRead(gpio_pin));		//主机接收到从机发送的响应信号（高电平）
		
		for (i = 0; i < 32; i++)
		{
			uint32 exit_time = 200;
			while((digitalRead(gpio_pin)&&exit_time!=0)) {exit_time--;delayMicroseconds(1);};	//数据位开始的54us低电平
			exit_time = 200;
			while(!digitalRead(gpio_pin)&&exit_time!=0) {exit_time--;delayMicroseconds(1);};;	//数据位开始的高电平就开始
			
			delayMicroseconds(32);			//跳过位数据，32us已经是数据0和数据1的差距点
			
			databuf *= 2;
			
			if (digitalRead(gpio_pin) == 1)
			{
				databuf++;
			}
		}
		
		for (i = 0; i < 8; i++)
        {
            uint32 exit_time = 200;
			while((digitalRead(gpio_pin)&&exit_time!=0)) {exit_time--;delayMicroseconds(1);};	//数据位开始的54us低电平
			exit_time = 200;
			while(!digitalRead(gpio_pin)&&exit_time!=0) {exit_time--;delayMicroseconds(1);};;	//数据位开始的高电平就开始
			
            delayMicroseconds(32);
			
            crc *= 2;  
            if (digitalRead(gpio_pin) == 1)
            {
                crc++;
            }
        }
		return 1;
	}
	else
	{
		return 0;
	}
}

uint32 dht11_update(void)
{
    DHT11_start(7);
    
    if (DHT11_read(7)) {
        uint32 re = databuf;
        databuf = 0;
        return re;
    }

    return 0;
}